## A propos Cette documentation présentera en détail l'architecture fondamentale requise pour mettre en place la fédération de CO avec le protocole ActivityPub. Elle expliquera les différents composants nécessaires et sa mise en œuvre. ## Composants L'implémentation se trouve dans le module `citizenToolKit`, plus précisément dans le dossier `components/activitypub`. Elle utilise l'espace de noms `PixelHumain\PixelHumain\modules\citizenToolKit\components\activitypub`. Le dossier racine contient trois sous-dossiers ainsi qu'un fichier de configuration : * **/type** : qui contient les classes représentant les différents types (vocabulaires) d'ActivityStream utilisés pour les activités dans ActivityPub * **/handlers** : qui contient toutes les classes qui gèrent les flux "inbox/outbox" * **/utils** : qui contient les classes et fonctions utilitaires * **config.php** : qui contient la configuration de l'instance. ### Type Ce dossier contient les mises en œuvre de tous les types recommandés dans [Activitystream 2.0 vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/), classés selon le`core type` et le `extend type`. La figure ci-dessous montre le diagramme de classe de types qu'on a implémenté: ![Diagramme de classe de types](https://gitlab.adullact.net/pixelhumain/codoc/-/raw/master/18%20-%20Activitypub/images/diagramme_de_classe_de_types.png). ### Handlers Ce dossier contient les classes qui gèrent les activités entrantes et sortantes de la fédération. Il y a une classe commune pour la gestion des événements appelée "Handler.php". Cette classe distribue les activités et appelle automatiquement la classe "handler" qui est responsable de l'activité en cours. Pour cela, la classe "handler" doit suivre les règles suivantes : 1. Elle doit être située dans le dossier `handlers/activity`. Par exemple, si on veut gérer les activités de type `create`, il faut placer le handler dans `handlers/create`. 2. Le nom de la classe handler doit être comme suit : `ActivityObjectHandler`, c'est-à-dire la concaténation du type d'activité, du type d'objet et du mot `Handler`. Par exemple, si on veut gérer l'activité de création d'une note, il faut créer une classe qui s'appelle `CreateNoteHandler`. 3. La classe handler doit hériter de la classe abstraite `AbstractHandler` et doit implémenter les deux méthodes suivantes : - **handleActivityFromClient** : appelé lorqu'un utilisateur dans CO envoye un activité (en effet il faut faire la féderation) - **handleActivityFromServer** : appelé lorqu'on reçoit un activité venant des autres instances. La figure ci-dessous montre le diagramme de classe de la gestion des activités: ![diagramme de classe handlers](https://gitlab.adullact.net/pixelhumain/codoc/-/raw/master/18%20-%20Activitypub/images/diagramme_de_classe_de_handlers.png) ### Utils Ce dossier contient uniquement les classes utilitaires nécessaires à notre application, notamment : * **HttpSignature** : cette classe permet de signer les activités à fédérer et de vérifier la signature des activités entrantes. Voir ici pour plus de details sur ([HTTP Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-08)) * **Request** : cette classe permet simplement de faire des requêtes HTTP et gère automatiquement la signature des données à envoyer. ### Config.php Ce fichier contient juste la configuration `HOSTNAME` de notre instance. ## Structure de données Pour faire fonctionner ActivityPub, nous avons créé trois nouvelles collections : * activitypub_activity * activitypub_object * et activitypub_cron ### La collection activitypub_activity Il s'agit d'une collection qui permet de stocker les différents flux d'activités. Elle comporte quatre entrées : * **uuid** : une chaîne de caractères qui sert d'identifiant unique pour chaque enregistrement * **from** : une chaîne de caractères indiquant le lien de la ressource à l'origine de l'activité * **to** : un tableau de chaînes de caractères contenant la liste des destinataires de l'activité * **activity** : un objet Activity Stream qui renferme les détails de l'activité. ### La collection activitypub_object Cette collection ne contient que les objets des activités fédérées par d'autres plateformes. Elle sert de cache pour garantir que les objets seront toujours disponibles même si l'instance source est indisponible. Elle se compose de seulement deux entrées, à savoir : * **UUID** : un identifiant unique ; * **Object** : un objet de flux d'activités. ### La collection activitypub_cron Cette collection permet d'enregistrer les activités des utilisateurs locaux afin de les envoyer ultérieurement via une tâche cron. Cela permet d'éviter aux utilisateurs d'attendre le processus de fédération. La collection contient 5 entrées : * **sender** : une chaîne de caractères représentant l'expéditeur * **receiver** : une chaîne de caractères représentant le destinataire * **data** : un objet activitystream à envoyer * **nbAttempt** : le nombre de tentatives d'envoi * **status** : l'état de l'envoi, "fail" ou "done". ## Mis en oeuvre ### Webfinger La première étape consiste à résoudre une ressource de type `user@domain` en utilisant l'endpoint `/.well-known/webfinger?resource=slug@domain`. Cela devrait renvoyer le [webfinger](https://www.rfc-editor.org/rfc/rfc7033) de la ressource demandé. Pour notre cas, l'alias `/.well-known/webfinger?resource=slug@domain` est redirigé vers `/api/activitypub/webfinger`. On a utilise `PixelHumain\PixelHumain\modules\api\controllers\ActivitypubController` comme controlleur et `\PixelHumain\PixelHumain\modules\api\controllers\activitypub\WebfingerAction` comme action. Le WebFinger doit renvoyer un lien qui permet de récupérer les informations relatives à la ressource en question. Cela nécessite la création d'un point d'accès qui renvoie les informations de cette ressource. Dans notre cas, cet point d'accès est `/api/activitypub/users/u/slug`. On utilise l'action `\PixelHumain\PixelHumain\modules\api\controllers\activitypub\GetActorAction`. #### Configuration de la redirection Pour qu'on puisse faire la redirection de `/.well-known/webfinger?resource=slug@domain` vers `/api/activitypub/webfinger` il faut qu'on fasse une réecriture d'url dans `.htaccess`. ``` RewriteEngine On RewriteCond %{REQUEST_URI} /\.well-known/webfinger$ RewriteCond %{QUERY_STRING} resource=([^&]+) RewriteRule ^(.*)$ /wf/%1.json [L] RewriteRule ^/.well-known/webfinger$ - [L,R=400] ``` **Remarque**: Pour obtenir le format JSON pour chaque ressource demandée, il est nécessaire d'ajouter `.json` à la fin de l'URL. Par exemple, pour accéder à la ressource `/api/activitypub/users/u/slug`, il faudrait faire `/api/activitypub/users/u/slug.json` #### WebfingerAction Pour générer le WebFinger d'une ressource, il suffit d'utiliser la classe WebFinger pour l'analyser et le créer renvoyer le `PixelHumain\PixelHumain\modules\citizenToolKit\components\activitypub\handlers\Webfinger` qui correspond à la ressource demandé. ### Inbox L'« inbox » le point d'entré à notre instance, il est accèssible via `/api/activitypub/inbox/u/slug`, et l'action correspondante est le `PixelHumain\PixelHumain\modules\api\controllers\activitypub\InboxAction`. Lorsqu'une activité est reçue, la méthode `PixelHumain\PixelHumain\modules\citizenToolKit\components\activitypub\type\Type::create` est appelée dans l'« InboxAction » pour créer une instance du type correspondant. Ensuite, la méthode `PixelHumain\PixelHumain\modules\citizenToolKit\components\activitypub\handlers\Handler::handle` est utilisée pour dispatcher l'activité vers le gestionnaire qui lui correspond. ### Outbox ...